using UnityEngine;
using Sirenix.OdinInspector;
using UnityEditor;

public partial class SfxProfileEditor
{
    private SfxProfilerScript playSfxScript;

    private ParticleSystem[] particleSystems;
    private Animation[] animations;
    
    [LabelText("特效偏移位置")]
    public Vector3 m_PosOffset = Vector3.zero;
    
    [DisableIf("@true"), LabelText("持续时间"), SuffixLabel("秒")]
    public float m_Duration = 0.0f;
#pragma warning disable 414
    private readonly float m_Min = 0.0f;
#pragma warning restore 414
    public enum MoveType
    {
        [LabelText("静态")]
        Static,
        [LabelText("Z方向（Loop）")]
        ZLoop,
        [LabelText("Z方向（PingPong）")]
        ZPingPong,
        [LabelText("圆周（Vertical）")]
        CircleVertical,
        [LabelText("圆周（Horizonal）")]
        CircleHorizonal,
        [LabelText("螺旋")]
        Spiral,
    }

    [LabelText("运动模拟"), PropertyOrder(0.0f)] public MoveType m_MoveType = MoveType.Static;

    protected override void OnEnable()
    {
        EditorApplication.update += OnUpdate;
    }

    protected override void OnDisable()
    {
        EditorApplication.update -= OnUpdate;
    }

    private void OnCloneSfx()
    {
        if (playSfxScript == null)
        {
            particleSystems = null;
            animations = null;
            return;
        }
        
        float duration = 0.0f;
        particleSystems = playSfxScript.GetComponentsInChildren<ParticleSystem>();
        for (int i = 0; i < particleSystems.Length; ++i)
        {
            ParticleSystem ps = particleSystems[i];
            if (ps.main.loop)
            {
                continue;
            }
            duration = Mathf.Max(duration, ps.main.duration);
        }
        
        animations = playSfxScript.GetComponentsInChildren<Animation>();
        for (int i = 0; i < animations.Length; ++i)
        {
            Animation a = animations[i];
            if (a.clip == null || !a.playAutomatically || a.clip.isLooping)
            {
                continue;
            }
            duration = Mathf.Max(duration, a.clip.length);
        }
        
        m_Duration = duration == 0.0f ? 3.0f : duration;
    }
    
    [Title("播放进度（秒）"), ShowIf("@" + nameof(m_Duration) + " > " + nameof(m_Min)), PropertyOrder(3.0f)]
    [DisableIf("@" + nameof(m_Profiling))]
    [HideLabel, ProgressBar(nameof(m_Min), nameof(m_Duration))]
    public float m_PlayProgress;
    private float m_LastPlayProgress;
    
    private bool m_IsPlaying = false;
    
    private float m_LastTime;
    private void OnUpdate()
    {
        float deltaTime = Time.realtimeSinceStartup - m_LastTime;
        m_LastTime = Time.realtimeSinceStartup;
        
        if (Mathf.Abs(m_LastPlayProgress - m_PlayProgress) > float.Epsilon)
        {
            UpdateAllRenderers();
            UpdateMove();
        }
        m_LastPlayProgress = m_PlayProgress;
            
        if (!m_IsPlaying)
        {
            return;
        }

        float lastProgress = m_PlayProgress;
        m_PlayProgress += deltaTime;
        if (m_PlayProgress > m_Duration)
        {
            m_PlayProgress = m_Duration;
        }
        if (Mathf.Abs(lastProgress - m_PlayProgress) > float.Epsilon)
        {
            Repaint();
        }
    }
    
    private void UpdateMove()
        {
            switch (m_MoveType)
            {
                case MoveType.ZLoop:
                {
                    float t = m_PlayProgress / m_Duration;
                    playSfxScript.transform.position = new Vector3(0.0f, 0.0f, t * 3.0f) + m_PosOffset;
                    break;
                }
                case MoveType.Static:
                {
                    playSfxScript.transform.position = Vector3.zero + m_PosOffset;
                    break;
                }
                case MoveType.ZPingPong:
                {
                    float t = m_PlayProgress / m_Duration;
                    if (t > 0.5f)
                    {
                        t = 1.0f - t;
                    }
                    playSfxScript.transform.position = new Vector3(0.0f, 0.0f, t * 3.0f) + m_PosOffset;
                    break;
                }
                case MoveType.CircleVertical:
                {
                    float t = m_PlayProgress / m_Duration;
                    float x = 1.5f * Mathf.Cos(t * 2 * Mathf.PI);
                    float y = 1.5f * Mathf.Sin(t * 2 * Mathf.PI);
                    playSfxScript.transform.position = new Vector3(x, y, 0.0f) + m_PosOffset;
                    break;
                }
                case MoveType.CircleHorizonal:
                {
                    float t = m_PlayProgress / m_Duration;
                    float x = 1.5f * Mathf.Cos(t * 2 * Mathf.PI);
                    float z = 1.5f * Mathf.Sin(t * 2 * Mathf.PI);
                    playSfxScript.transform.position = new Vector3(x, 0.0f, z) + m_PosOffset;
                    break;
                }
                case MoveType.Spiral:
                {
                    float t = m_PlayProgress / m_Duration;
                    float x = 0.5f * Mathf.Cos(t * 6 * Mathf.PI);
                    float y = 0.5f * Mathf.Sin(t * 6 * Mathf.PI);
                    playSfxScript.transform.position = new Vector3(x, y, t * 6.0f) + m_PosOffset;
                    break;
                }
            }
        }

    private void UpdateAllRenderers()
    {
        for (int i = 0; i < particleSystems.Length; ++i)
        {
            ParticleSystem particleSystem = particleSystems[i];
            if (particleSystem == null)
            {
                continue;
            }
            // 关闭随机数种子防止鬼畜
            if (particleSystem.useAutoRandomSeed)
            {
                particleSystem.useAutoRandomSeed = false;
            }
            if (particleSystem.trails.enabled)
            {
                particleSystem.Simulate(m_PlayProgress, false, false);
            }
            else
            {
                particleSystem.Simulate(m_PlayProgress, false);
            }
        }

        for (int i = 0; i < animations.Length; ++i)
        {
            Animation animation = animations[i];
            if (animation == null || animation.clip == null || !animation.playAutomatically)
            {
                continue;
            }
            AnimationState state = animation[animation.clip.name];
            if (state != null)
            {
                state.enabled = true;
                state.time = m_PlayProgress;
                state.weight = 1.0f;
                
                animation.Sample();
                
                state.enabled = false;
            }
        }
    }
}